From 3a3034d1015f9360068d8719e22afbe06a2bedbb Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Fri, 20 Feb 2009 11:11:40 +0000 Subject: [PATCH] [VTD] Utilise the snoop control capability in shadow with VT-d code We compute the shadow PAT index in leaf page entries now as: 1) No VT-d assigned: let shadow PAT index as WB, handled already in shadow code before. 2) direct assigned MMIO area: let shadow code compute the shadow PAT with gMTRR=UC and gPAT value. 3) Snoop control enable: let shadow PAT index as WB. 4) Snoop control disable: let shadow code compute the shadow PAT with gMTRR and gPAT, handled already in shadow code before Signed-off-by: Xin, Xiaohui --- xen/arch/x86/hvm/mtrr.c | 19 ++++++++++++++----- xen/arch/x86/mm/shadow/multi.c | 19 ++++++++++++++++++- xen/include/asm-x86/mtrr.h | 3 ++- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/xen/arch/x86/hvm/mtrr.c b/xen/arch/x86/hvm/mtrr.c index 6f64062cf9..e1448d99ee 100644 --- a/xen/arch/x86/hvm/mtrr.c +++ b/xen/arch/x86/hvm/mtrr.c @@ -351,11 +351,18 @@ static uint8_t page_pat_type(uint64_t pat_cr, uint32_t pte_flags) static uint8_t effective_mm_type(struct mtrr_state *m, uint64_t pat, paddr_t gpa, - uint32_t pte_flags) + uint32_t pte_flags, + uint8_t gmtrr_mtype) { uint8_t mtrr_mtype, pat_value, effective; - - mtrr_mtype = get_mtrr_type(m, gpa); + + /* if get_pat_flags() gives a dedicated MTRR type, + * just use it + */ + if ( gmtrr_mtype == NO_HARDCODE_MEM_TYPE ) + mtrr_mtype = get_mtrr_type(m, gpa); + else + mtrr_mtype = gmtrr_mtype; pat_value = page_pat_type(pat, pte_flags); @@ -367,7 +374,8 @@ static uint8_t effective_mm_type(struct mtrr_state *m, uint32_t get_pat_flags(struct vcpu *v, uint32_t gl1e_flags, paddr_t gpaddr, - paddr_t spaddr) + paddr_t spaddr, + uint8_t gmtrr_mtype) { uint8_t guest_eff_mm_type; uint8_t shadow_mtrr_type; @@ -378,7 +386,8 @@ uint32_t get_pat_flags(struct vcpu *v, /* 1. Get the effective memory type of guest physical address, * with the pair of guest MTRR and PAT */ - guest_eff_mm_type = effective_mm_type(g, pat, gpaddr, gl1e_flags); + guest_eff_mm_type = effective_mm_type(g, pat, gpaddr, + gl1e_flags, gmtrr_mtype); /* 2. Get the memory type of host physical address, with MTRR */ shadow_mtrr_type = get_mtrr_type(&mtrr_state, spaddr); diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 51566b2eb3..56fc5635e4 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -546,15 +546,32 @@ _sh_propagate(struct vcpu *v, !is_xen_heap_mfn(mfn_x(target_mfn)) ) { unsigned int type; + + /* compute the PAT index for shadow page entry when VT-d is enabled + * and device assigned. + * 1) direct MMIO: compute the PAT index with gMTRR=UC and gPAT. + * 2) if enables snoop control, compute the PAT index as WB. + * 3) if disables snoop control, compute the PAT index with + * gMTRR and gPAT. + */ if ( hvm_get_mem_pinned_cacheattr(d, gfn_x(target_gfn), &type) ) sflags |= pat_type_2_pte_flags(type); else if ( d->arch.hvm_domain.is_in_uc_mode ) sflags |= pat_type_2_pte_flags(PAT_TYPE_UNCACHABLE); + else if ( p2mt == p2m_mmio_direct ) + sflags |= get_pat_flags(v, + gflags, + gfn_to_paddr(target_gfn), + ((paddr_t)mfn_x(target_mfn)) << PAGE_SHIFT, + MTRR_TYPE_UNCACHABLE); + else if ( iommu_snoop ) + sflags |= pat_type_2_pte_flags(PAT_TYPE_WRBACK); else sflags |= get_pat_flags(v, gflags, gfn_to_paddr(target_gfn), - ((paddr_t)mfn_x(target_mfn)) << PAGE_SHIFT); + ((paddr_t)mfn_x(target_mfn)) << PAGE_SHIFT, + NO_HARDCODE_MEM_TYPE); } // Set the A&D bits for higher level shadows. diff --git a/xen/include/asm-x86/mtrr.h b/xen/include/asm-x86/mtrr.h index 65d56f7d8e..03285db5bd 100644 --- a/xen/include/asm-x86/mtrr.h +++ b/xen/include/asm-x86/mtrr.h @@ -11,6 +11,7 @@ #define MTRR_TYPE_WRBACK 6 #define MTRR_NUM_TYPES 7 #define MEMORY_NUM_TYPES MTRR_NUM_TYPES +#define NO_HARDCODE_MEM_TYPE MTRR_NUM_TYPES #define NORMAL_CACHE_MODE 0 #define NO_FILL_CACHE_MODE 2 @@ -63,7 +64,7 @@ extern int mtrr_del(int reg, unsigned long base, unsigned long size); extern int mtrr_del_page(int reg, unsigned long base, unsigned long size); extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi); extern u32 get_pat_flags(struct vcpu *v, u32 gl1e_flags, paddr_t gpaddr, - paddr_t spaddr); + paddr_t spaddr, uint8_t gmtrr_mtype); extern uint8_t epte_get_entry_emt( struct domain *d, unsigned long gfn, unsigned long mfn, uint8_t *igmt, int direct_mmio); -- 2.30.2